package com.authine.cloudpivot.web.api.controller.base;

import com.alibaba.dubbo.common.utils.CollectionUtils;
import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.authine.cloudpivot.engine.api.model.application.AppFunctionModel;
import com.authine.cloudpivot.engine.api.model.application.AppPackageModel;
import com.authine.cloudpivot.engine.api.model.bizmodel.BizPropertyModel;
import com.authine.cloudpivot.engine.api.model.organization.*;
import com.authine.cloudpivot.engine.api.model.permission.*;
import com.authine.cloudpivot.engine.component.query.api.FilterExpression;
import com.authine.cloudpivot.engine.component.query.api.helper.Q;
import com.authine.cloudpivot.engine.enums.ErrCode;
import com.authine.cloudpivot.engine.enums.type.*;
import com.authine.cloudpivot.web.api.exception.PortalException;
import com.authine.cloudpivot.web.api.helper.PermissionHelper;
import com.authine.cloudpivot.web.api.util.AuthUtils;
import com.authine.cloudpivot.web.api.view.organization.UserSelectionVO;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 权限控制层
 */
@Slf4j
public class PermissionController extends BaseController {
    //分隔符
    protected final static String regex = "##_&&";
    /**
     * 本部门
     */
    private static final String SELF_D = "SELF_D";

    /**
     * 本人
     */
    private static final String SELF_P = "SELF_P";
    private static final String APPNMGCACHEBASE = "app_mng:perm:department:id:";

    /**
     * 数据权限公共方法
     * userType:0普通用户，1系统管理员，2为应用管理员其数据权限为普通用户权限，3数据管理员
     * appPermission：数据管理员是否有模型对应应用权限如果为ture则有数据权限
     * schemaPermission：业务模型权限，普通或没有该应用权限的数据管理员需要通过业务模型权限相关对象获取对应的数据权限
     *
     * @param userId
     * @param schemaCode
     * @return
     */
//	protected Map<String, Object> getDataPermissions(String userId, String schemaCode) {
//		Map<String, Object> map = new HashMap<>();
//		map.put("userType", 0);
//		//处理数据管理员和超级管理员权限
//		AdminModel managerModel = getDataManaerByUserId(userId);
//		if (managerModel != null && managerModel.getAdminType().equals(AdminType.SYS_MNG)) {
//			map.put("userType", AdminType.SYS_MNG.getIndex());
//			return map;
//		}
//		if (managerModel != null && managerModel.getAdminType().equals(AdminType.DATA_MNG)) {
//			map.put("userType", AdminType.DATA_MNG.getIndex());
//			//校验schemaCode是否在其所在的应用下
//			if (checkManagerApp(managerModel, schemaCode)) {
//				map.put("appPermission", true);
//				return map;
//			}
//			map.put("appPermission", false);
//		}
//		List<AppFunctionPermissionModel> appFunctionPermissionModels = getCommonDataPermission(userId, schemaCode);
//		map.put("schemaPermission", appFunctionPermissionModels);
//		return map;
//	}
    private static final String APPNMGCHILDCACHEBASE = "app_mng:perm:department:child:id:";
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 获取用户最高权限配置信息，用于列表查询条件
     *
     * @param schemaCode 模型编码
     * @param userId     用户id
     * @return 权限
     */
    protected List<AppFunctionPermissionModel> getCommonDataPermission(String userId, String schemaCode, Boolean isOwner, List<PermissionGroupModel> permissionGroupModels) {

        List<AppFunctionPermissionModel> appFunctionPermissionModels = PermissionHelper.getCommonDataPermission(schemaCode, permissionGroupModels, isOwner);
        if (CollectionUtils.isEmpty(appFunctionPermissionModels)) {
            AppFunctionPermissionModel appFunctionPermissionModel = new AppFunctionPermissionModel();
            appFunctionPermissionModel.setEditable(true);
            appFunctionPermissionModel.setSchemaCode(schemaCode);
            appFunctionPermissionModel.setVisible(true);
            appFunctionPermissionModel.setCreatable(true);
            appFunctionPermissionModel.setDataPermissionType(DataPermissionType.ONLY_MYSELF);
            appFunctionPermissionModel.setDeletable(true);
            appFunctionPermissionModel.setExportable(true);
            appFunctionPermissionModel.setImportable(true);
            List<AppFunctionPermissionModel> appFunctionPermissionModelList = new ArrayList<>();
            appFunctionPermissionModelList.add(appFunctionPermissionModel);
            return appFunctionPermissionModelList;
        }
        for (AppFunctionPermissionModel appFunctionPermissionModel : appFunctionPermissionModels) {
            if (appFunctionPermissionModel.getDataPermissionType().equals(DataPermissionType.CUSTOM)) {
                appFunctionPermissionModel.setConditions(getPermissionManagementFacade().getAppFunctionPermissionConditionsByFunctionId(appFunctionPermissionModel.getId()));
            }
        }
        return appFunctionPermissionModels;
    }

    /**
     * 检验管理员是否配置有模型权限
     *
     * @param manager    管理员
     * @param schemaCode 业务模型编码
     * @return Boolean
     */
    protected Boolean checkManagerApp(AdminModel manager, String schemaCode) {
        List<AppPackageScopeModel> appPackages = manager.getAppPackages();
        if (CollectionUtils.isNotEmpty(appPackages)) {
            AppFunctionModel appFunction = getAppManagementFacade().getAppFunctionByCode(schemaCode);
            if (Objects.nonNull(appFunction)) {
                for (AppPackageScopeModel appPackage : appPackages) {
                    if (Objects.equals(appFunction.getAppCode(), appPackage.getCode())) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    protected Boolean checkManagerApp(AdminModel manager, AppFunctionModel appFunction) {
        List<AppPackageScopeModel> appPackages = manager.getAppPackages();
        if (CollectionUtils.isNotEmpty(appPackages) && Objects.nonNull(appFunction)) {
            for (AppPackageScopeModel appPackage : appPackages) {
                if (Objects.equals(appFunction.getAppCode(), appPackage.getCode())) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 判断是否是对应应用的数据管理员：DATA_MNG
     *
     * @param schemaCode 业务模型编码
     * @return
     */
    protected Boolean isDataManagerForApp(String schemaCode) {
        return isDataManagerForApp(AuthUtils.getUserId(), schemaCode);
    }

    protected Boolean isDataManagerForApp(String userId, String schemaCode) {
        List<AdminModel> managers = getPermissionManagementFacade().getAdminByUserId(userId);
        if (CollectionUtils.isNotEmpty(managers)) {
            List<AdminModel> models = managers.stream().filter(mng -> Objects.equals(mng.getAdminType(), AdminType.DATA_MNG)).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(models)) {
                for (AdminModel manager : models) {
                    return checkManagerApp(manager, schemaCode);
                }
            }
        }
        return Boolean.FALSE;
    }

    /**
     * 获取列表数据权限,增加对拥有者修改权限的判断并结合数据可见权限
     *
     * @param userId     用户id
     * @param schemaCode 业务模型编码
     * @return FilterExpr
     */
    protected FilterExpression getAuthFilters(String userId, String schemaCode, Boolean isOwner) {

        AppFunctionModel appFunction = getAppManagementFacade().getAppFunctionByCode(schemaCode);
        AppPackagePermissionModel appPackagePermissionModel = getPermissionManagementFacade().getAppPackagePermission(appFunction.getAppCode());
        if (appPackagePermissionModel == null) {
            return FilterExpression.empty;
        }
        if (!appPackagePermissionModel.getAppPackage().getEnabled()) {
            throw new PortalException(ErrCode.APP_FORBIDDENED, ErrCode.APP_FORBIDDENED.getErrMsg());
        }

        List<PermissionGroupModel> permissionGroupModels = getPermissionManagementFacade().getPermissionGroupsByAppCodeAndUserId(appFunction.getAppCode(), userId);
//        if (CollectionUtils.isEmpty(permissionGroupModels)) {
//            return FilterExpression.empty;
//        }

        List<AppFunctionPermissionModel> appFunctionPermissionModels;
        if (appPackagePermissionModel.getVisibleType().equals(VisibleType.ALL_VISIABLE)) {
            AppFunctionPermissionModel appFunctionPermissionModel = new AppFunctionPermissionModel();
            appFunctionPermissionModel.setEditable(true);
            appFunctionPermissionModel.setSchemaCode(schemaCode);
            appFunctionPermissionModel.setVisible(true);
            appFunctionPermissionModel.setCreatable(true);
            appFunctionPermissionModel.setDataPermissionType(DataPermissionType.ONLY_MYSELF);
            appFunctionPermissionModel.setDeletable(true);
            appFunctionPermissionModel.setExportable(true);
            appFunctionPermissionModel.setImportable(true);
            List<AppFunctionPermissionModel> appFunctionPermissionModelList = new ArrayList<>();
            appFunctionPermissionModelList.add(appFunctionPermissionModel);

            appFunctionPermissionModels = appFunctionPermissionModelList;
        } else {
            //获取最高查询条件权限
            appFunctionPermissionModels = getCommonDataPermission(userId, schemaCode, isOwner, permissionGroupModels);
        }

        //List<AppFunctionPermissionModel> appFunctionPermissionModels = getCommonDataPermission(userId, schemaCode, isOwner);
        //判断用户类型
        AdminModel manager = getDataManaerByUserId(userId);
        Boolean isAdmin = isAdmin(userId) || isSysManager(userId);
        Boolean isDataMng = isDataManagerForApp(userId, schemaCode);
        DataPermissionType permissionType = null;
        List<FilterExpression> filterExprs = new ArrayList<>();

        //如果菜单数据没有权限，就不要往下查看验证数据的权限了
        AppPackageModel appPackage = getAppManagementFacade().getAppPackageByCode(appFunction.getAppCode());
        //获取所有目录

//        List<AppFunctionModel> appFunctions = getAppManagementFacade().getAppFunctionsByParentId(appPackage.getId(), userId, permissionGroupModels, true, false);
        List<AppFunctionModel> appFunctions = getAppManagementFacade().getAppFunctionsByParentIdAndFunctionCode(appPackage.getId(),appFunction.getCode(), userId, permissionGroupModels, true, false);
        if(CollectionUtils.isEmpty(appFunctions)){
            throw new PortalException(40002, "当前列表数据没有查看权限");
//            return FilterExpression.empty;
        }


        if (CollectionUtils.isNotEmpty(appFunctionPermissionModels)) {
            //仅可见的数据
            appFunctionPermissionModels = appFunctionPermissionModels.stream().filter(t -> t.getVisible()).collect(Collectors.toList());
        }
        boolean empty = CollectionUtils.isEmpty(appFunctionPermissionModels);
        if (isOwner && (!empty) && !isAdmin && !isDataMng) {
            appFunctionPermissionModels = appFunctionPermissionModels.stream().filter(t -> t.getEditOwnerAble()).collect(Collectors.toList());
        }
        if (!isAdmin && !isDataMng) {
            if (CollectionUtils.isEmpty(appFunctionPermissionModels)) {
                throw new PortalException(ErrCode.NO_SCHEMA_DATA_AUTHROITY, ErrCode.NO_SCHEMA_DATA_AUTHROITY.getErrMsg());
            }
        }
        if (CollectionUtils.isNotEmpty(appFunctionPermissionModels)) {
            //获取最高权限类型
            List<AppFunctionPermissionModel> allPermissions = appFunctionPermissionModels.stream().filter(model -> model.getDataPermissionType().equals(DataPermissionType.ALL)).collect(Collectors.toList());

            List<AppFunctionPermissionModel> rolesPermissions = appFunctionPermissionModels.stream().filter(model -> model.getDataPermissionType().equals(DataPermissionType.ROLE_MANAGE_SCOPE)).collect(Collectors.toList());

            permissionType = appFunctionPermissionModels.get(0).getDataPermissionType();

            if (CollectionUtils.isNotEmpty(allPermissions)) {
                return FilterExpression.empty;
            } else if (CollectionUtils.isNotEmpty(rolesPermissions) && !isAdmin) {
                //获取当前用户的管理范围过滤
                List<RoleUserModel> usersRoles = getOrganizationFacade().getRoleUsersByUserId(userId);
                if (CollectionUtils.isNotEmpty(usersRoles)) {

                    //过滤出权限组包含的角色id
                    Set<String> roleIdList = Sets.newHashSet();
                    List<String> permissionGroupIdList = rolesPermissions.stream().map(AppFunctionPermissionModel::getPermissionGroupId).collect(Collectors.toList());
                    permissionGroupModels.stream().filter(group -> !StringUtils.isBlank(group.getRoles()) && permissionGroupIdList.contains(group.getId())).forEach(group -> {
                        JSONArray jsonArray = JSON.parseArray(group.getRoles());
                        for (Object object : jsonArray) {
                            JSONObject jsonObject = (JSONObject) object;
                            String roleId = jsonObject.getString("id");
                            roleIdList.add(roleId);
                        }
                    });

                    final Set<String> scopeIds = Sets.newHashSet();
                    final Set<String> usscopeIds = Sets.newHashSet();
                    for (RoleUserModel roleUserModel : usersRoles) {
                        //角色组设置的角色与用户拥有的角色的交集
                        if(!roleIdList.contains(roleUserModel.getRoleId())) {
                            continue;
                        }
                        String scope = roleUserModel.getOuScope();
                        if(!StringUtils.isBlank(scope)) {
                            try {
                                scopeIds.addAll(JSON.parseArray(scope, String.class));
                            } catch (Exception e) {
                                log.error("解析角色范围异常.", e);
                            }
                        }
                        String usscope = roleUserModel.getUsScope();
                        if(!StringUtils.isBlank(usscope)) {
                            try {
                                usscopeIds.addAll(JSON.parseArray(usscope, String.class));
                            } catch (Exception e) {
                                log.error("解析角色范围(用户)异常.", e);
                            }
                        }
                    }

                    final List<String> userScopes = new ArrayList<>(usscopeIds);
                    final List<String> deptScopes = new ArrayList<>(scopeIds);
/*
                    final List<String> userScopes = Lists.newArrayList();
                    final List<String> deptScopes = Lists.newArrayList();
                    for (String id : scopeIds) {
                        if(getOrganizationFacade().getUser(id) != null) {
                            userScopes.add(id);
                        }
                        if(getOrganizationFacade().getDepartment(id) != null) {
                            deptScopes.add(id);
                        }
                    }
*/

                    //角色管理范围-用户
                    final List<FilterExpression> filterExpressionList = Lists.newArrayList();
                    if(org.apache.commons.collections4.CollectionUtils.isNotEmpty(userScopes)) {
                        filterExpressionList.add(Q.it("owner", FilterExpression.Op.In, userScopes));
                    }
                    //角色管理范围-部门
                    if(org.apache.commons.collections4.CollectionUtils.isNotEmpty(deptScopes)) {
                        List<DepartmentModel> departmentModels = getOrganizationFacade().getDepartmentsChildList(deptScopes, true);
                        if (CollectionUtils.isNotEmpty(departmentModels)) {
                            filterExpressionList.add(Q.it("ownerDeptId", FilterExpression.Op.In, departmentModels.stream().map(DepartmentModel::getId).collect(Collectors.toList())));
                        }
                    }
                    if(filterExpressionList.size() == 1) {
                        filterExprs.add(filterExpressionList.get(0));
                    } else if(filterExpressionList.size() > 1) {
                        filterExprs.add(Q.or(filterExpressionList));
                    } else {
                        //有角色管理范围，但是管理范围为空时
                        filterExprs.add(Q.it("ownerDeptId", FilterExpression.Op.Eq, "1"));
                    }
                }
            }
        } else {
            if (!isAdmin) {
                filterExprs.add(Q.it("owner", FilterExpression.Op.Eq, userId));
            }
        }

        //数据管理员权限
        if (isDataMng) {
            List<DepartmentScopeModel> departments = manager.getDepartments();
            filterExprs = getManagerFilter(departments);
        }
        //其他用户权限
        getCommentUserFilter(filterExprs, permissionType, appFunctionPermissionModels, userId, isAdmin);
        if (CollectionUtils.isNotEmpty(filterExprs)) {
            if (filterExprs.size() > 1) {
                return Q.or(filterExprs);
            } else if (filterExprs.size() == 1) {
                return filterExprs.get(0);
            }
        }
        return FilterExpression.empty;
    }

    /**
     * 获取管理员配置信息
     *
     * @param departments 部门
     * @return List
     */
    protected List<FilterExpression> getManagerFilter(List<DepartmentScopeModel> departments) {
        List<FilterExpression> filterExprs = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(departments)) {
            for (DepartmentScopeModel department : departments) {
                //此处不应该获取id应该是querCode
                if (department.getUnitType() == UnitType.DEPARTMENT) {
                    String queryCode = department.getQueryCode();
                    if (StringUtils.isNotEmpty(queryCode) && queryCode.contains("_")){
                        queryCode=queryCode.replace("_","\\_");
                    }
                    filterExprs.add(Q.it("ownerDeptQueryCode", FilterExpression.Op.LLike, queryCode));
                }
                if (department.getUnitType() == UnitType.USER && !"2ccf3b346706a6d3016706dc51c0022b".equals(department.getUnitId())) {
                    filterExprs.add(Q.it("owner", FilterExpression.Op.Eq, department.getUnitId()));
                }
            }
        }

        return filterExprs;
    }

    /**
     * 获取普通用户权限
     *
     * @param filterExprs
     * @param permissionType
     */
    protected void getCommentUserFilter(List<FilterExpression> filterExprs, DataPermissionType permissionType, List<AppFunctionPermissionModel> appFunctionPermissionModels, String userId, Boolean isAdmin) {
        if (permissionType == null) {
            return;
        }
        FilterExpression authFilter = FilterExpression.empty;
        boolean filterDept = permissionType.equals(DataPermissionType.MY_DEPARTMENT);
        boolean filterMySelf = permissionType.equals(DataPermissionType.ONLY_MYSELF);
        boolean filterCustom = permissionType.equals(DataPermissionType.CUSTOM);
        if (CollectionUtils.isNotEmpty(appFunctionPermissionModels)) {
            for (AppFunctionPermissionModel appFunctionPermissionModel : appFunctionPermissionModels) {
                if (appFunctionPermissionModel.getDataPermissionType().equals(DataPermissionType.MY_DEPARTMENT)) {
                    filterDept = true;
                }
                if (appFunctionPermissionModel.getDataPermissionType().equals(DataPermissionType.ONLY_MYSELF)) {
                    filterMySelf = true;
                }
                if (appFunctionPermissionModel.getDataPermissionType().equals(DataPermissionType.CUSTOM)) {
                    filterCustom = true;
                }
            }
        }
        if ((filterDept || filterMySelf || filterCustom) && !isAdmin) {
            if (filterDept) {
                List<DepartmentModel> departments = getOrganizationFacade().getDepartmentsByUserId(userId);
                filterExprs.addAll(getDepartFilters(departments));
            }
            if (filterMySelf) {
                if (!"2ccf3b346706a6d3016706dc51c0022b".equals(userId)) {
                    authFilter = Q.it("owner", FilterExpression.Op.Eq, userId);
                }
            }

            disposeCustomFilter(filterExprs, appFunctionPermissionModels, userId);
        }
/*        if (permissionType.equals(DataPermissionType.MY_DEPARTMENT) && !isAdmin) {
            //获取用户所在的部门
            List<DepartmentModel> departments = getOrganizationFacade().getDepartmentsByUserId(userId);

//			filterExprs.addAll(getDepartFilter(departments.stream().map(DepartmentModel::getQueryCode).collect(Collectors.toList())));
            filterExprs.addAll(getDepartFilters(departments));
            disposeCustomFilter(filterExprs, appFunctionPermissionModels, userId);
        }
        if (permissionType.equals(DataPermissionType.ONLY_MYSELF) && !isAdmin) {
            disposeCustomFilter(filterExprs, appFunctionPermissionModels, userId);
            if (!"2ccf3b346706a6d3016706dc51c0022b".equals(userId)) {
                authFilter = Q.it("owner", FilterExpression.Op.Eq, userId);
            }
        }*/
        if (authFilter != FilterExpression.empty) {
            filterExprs.add(authFilter);
        }
/*        if (permissionType.equals(DataPermissionType.CUSTOM) && !isAdmin) {
            disposeCustomFilter(filterExprs, appFunctionPermissionModels, userId);
        }*/
    }

    /**
     * 解析自定义权限
     *
     * @param filterExprs
     * @param appFunctionPermissionModels
     */
    protected void disposeCustomFilter(List<FilterExpression> filterExprs, List<AppFunctionPermissionModel> appFunctionPermissionModels) {
        disposeCustomFilter(filterExprs, appFunctionPermissionModels, this.getUserId());
    }

    /**
     * 解析自定义权限(通过传入userid而不是从请求中获取)
     *
     * @param filterExprs
     * @param appFunctionPermissionModels
     */
    protected void disposeCustomFilter(List<FilterExpression> filterExprs, List<AppFunctionPermissionModel> appFunctionPermissionModels, String userId) {
        if (CollectionUtils.isEmpty(appFunctionPermissionModels)) {
            return;
        }
        List<AppFunctionPermissionModel> appFunctionPermissions = appFunctionPermissionModels.stream().filter(t -> t.getDataPermissionType().equals(DataPermissionType.CUSTOM)).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(appFunctionPermissions)) {
            return;
        }
        /**自定义查询条件业务字段是选人控件时，支持本人或本部门*/
        customPermBizSelection(appFunctionPermissions, userId);
        String schemaCode = appFunctionPermissions.get(0).getSchemaCode();
        List<BizPropertyModel> properties = getAppManagementFacade().getBizSchemaBySchemaCode(schemaCode).getProperties();
        for (AppFunctionPermissionModel appFunctionPermission : appFunctionPermissions) {
            List<AppFunctionPermissionConditionModel> appFunctionPermissionConditions = appFunctionPermission.getConditions();
            if (CollectionUtils.isEmpty(appFunctionPermissionConditions)) {
                //默认自己的可见
                filterExprs.add(Q.it("owner", FilterExpression.Op.Eq, userId));
                continue;
            }
            List<FilterExpression> filterExprsTemplates = new ArrayList<>();
            for (AppFunctionPermissionConditionModel appFunctionPermissionCondition : appFunctionPermissionConditions) {
                FilterExpression.Op op = disposeDperator(appFunctionPermissionCondition);

                FilterExpression.Item it = parseFilterExpression(appFunctionPermissionCondition, properties);

                FilterExpression item = FilterExpression.empty;
                if (StringUtils.isNotEmpty(appFunctionPermissionCondition.getValue()) && (op.equals(FilterExpression.Op.NotEq) || op.equals(FilterExpression.Op.NotLike))) {
                    item = Q.it(appFunctionPermissionCondition.getPropertyCode(), FilterExpression.Op.Eq, null);
                }

                if (item.isEmpty() && Objects.isNull(it.value)) {
                    if (appFunctionPermissionCondition.getOperatorType() == OperatorType.IS_NOT_NULL) {
                        filterExprsTemplates.add(Q.and(it, Q.it(it.field, it.op, "")));
                    } else {
                        filterExprsTemplates.add(Q.or(it, Q.it(it.field, it.op, "")));
                    }
                    continue;
                }

                //暂时看不懂 不知道咋改
                String value = it.value.toString();
                String[] split = value.split(regex);
                if (item.isEmpty()) {

                    if (split.length > 1) {
                        log.info("多值过滤条件field={},op={},value={}", it.field, it.op, it.value);
                        //拓展多条件，目前只针对数据权限的选人控件增加的拓展，后续需要拓展其他字段开发者自行参考
                        if (split.length == 2) {
                            filterExprsTemplates.add(Q.or(Q.it(it.field, it.op, split[0]), Q.it(it.field, it.op, split[1])));
                        } else {
                            FilterExpression.Item[] items = new FilterExpression.Item[split.length - 2];
                            for (int x = 0; x < items.length; x++) {
                                items[x] = Q.it(it.field, it.op, split[x + 2]);
                            }
                            filterExprsTemplates.add(Q.or(Q.it(it.field, it.op, split[0]), Q.it(it.field, it.op, split[1]), items));
                        }

                    } else {
                        if (appFunctionPermissionCondition.getOperatorType() == OperatorType.IS_NOT_NULL) {
                            filterExprsTemplates.add(Q.and(it, Q.it(it.field, it.op, "")));
                        } else {
                            filterExprsTemplates.add(it);
                        }
                    }
                    continue;
                }
                if (split.length > 1) {
                    log.info("多值过滤条件field={},op={},value={}", it.field, it.op, it.value);
                    //拓展多条件，目前只针对数据权限的选人控件增加的拓展，后续需要拓展其他字段开发者自行参考
                    if (split.length == 2) {
                        filterExprsTemplates.add(Q.or(Q.and(Q.it(it.field, it.op, split[0]), Q.it(it.field, it.op, split[1])), item));
                    } else {
                        FilterExpression.Item[] items = new FilterExpression.Item[split.length - 2];
                        for (int x = 0; x < items.length; x++) {
                            items[x] = Q.it(it.field, it.op, split[x + 2]);
                        }
//                        filterExprsTemplates.add(Q.and(Q.it(it.field,it.op,split[0]),Q.it(it.field,it.op,split[1]),items));
                        filterExprsTemplates.add(Q.or(Q.and(Q.it(it.field, it.op, split[0]), Q.it(it.field, it.op, split[1]), items), item));
                    }
                } else {
                    filterExprsTemplates.add(Q.or(it, item));
                }

            }
            if (CollectionUtils.isNotEmpty(filterExprsTemplates)) {
                if (appFunctionPermission.getFilterType().equals(FilterType.ALL)) {
                    if (filterExprsTemplates.size() > 1) {
                        filterExprs.add(Q.and(filterExprsTemplates));
                    }
                } else {
                    if (filterExprsTemplates.size() > 1) {
                        filterExprs.add(Q.or(filterExprsTemplates));
                    }
                }
                if (filterExprsTemplates.size() == 1) {
                    filterExprs.add(filterExprsTemplates.get(0));
                }
            }
        }
    }

    /**
     * 自定义查询条件业务字段是选人控件时，支持本人或本部门
     *
     * @param appFunctionPermissions
     */
    private void customPermBizSelection(List<AppFunctionPermissionModel> appFunctionPermissions, String userId) {
        /**自定义查询条件业务字段是选人控件时，支持本人或本部门*/
        for (int i = 0; i < appFunctionPermissions.size(); i++) {
            appFunctionPermissions.get(i).getConditions().forEach(t -> {
                /**若是本部门，查询到当前用户的主部门ID，填充自定义查询条件value*/
                if (Objects.equals(t.getValue(), SELF_D)) {
                    UserModel userModel = this.getOrganizationFacade().getUser(userId, Boolean.FALSE);
//                    String deptId = Objects.nonNull(userModel) ? userModel.getDepartmentId() : null;

                    if (Objects.equals(t.getOperatorType(), OperatorType.CONTAINS) || Objects.equals(t.getOperatorType(), OperatorType.NOT_CONTAINS)) {
//                        DepartmentModel department = this.getOrganizationFacade().getDepartment(deptId);
                        //用户部门集合，包括用户自己所在的部门和上级部门,用符号 隔开
                        String deptIdCollect = getUserDeptIdsAndParentDeptIds(userId);
                        /**包含、不包含*/
                        t.setValue(deptIdCollect);
                    } else {
                        /**等于、不等于*/
                        String userDeptIds = getUserDeptIds(userId);
                        String[] split = userDeptIds.split(regex);
                        if (split.length > 1) {
                            StringBuilder sb = new StringBuilder();
                            for (String deptId : split) {
                                String idTemp = "[{\"id\":\"" + deptId + "\",\"type\":1}]";
                                sb.append(idTemp).append(regex);
                            }
                            t.setValue(sb.toString());
                        } else {
                            t.setValue("[{\"id\":\"" + split[0] + "\",\"type\":1}]");
                        }

                    }
                }
                /**若是本人，查询到当前用户的userID，填充自定义查询条件value*/
                if (Objects.equals(t.getValue(), SELF_P)) {
                    if (Objects.equals(t.getOperatorType(), OperatorType.CONTAINS) || Objects.equals(t.getOperatorType(), OperatorType.NOT_CONTAINS)) {
                        /**包含、不包含*/
                        t.setValue(userId);
                    } else {
                        /**等于、不等于*/
                        t.setValue("[{\"id\":\"" + userId + "\",\"type\":3}]");
                    }
                }
            });
        }
    }

    /**
     * 获取当前登录用户本部门，包括自己所在部门和上级部门id集合，用{@link #regex} 符号隔开
     *
     * @param userId
     * @return
     */
    protected String getUserDeptIdsAndParentDeptIds(String userId) {
        //用户部门
        List<DepartmentUserModel> departmentUserModels = this.getOrganizationFacade().getDepartmentUsersByUserId(userId);
        List<String> deptList = departmentUserModels.stream().map(DepartmentUserModel::getDeptId).collect(Collectors.toList());
        departmentUserModels.forEach(model -> {
            List<DepartmentModel> allParentDepartment = this.getOrganizationFacade().getParentDepartments(model.getDeptId());
            deptList.addAll(allParentDepartment.stream().map(DepartmentModel::getId).collect(Collectors.toList()));
        });
        return deptList.stream().distinct().collect(Collectors.joining(regex));
    }

    /**
     * 获取当前登录用户本部门，包括自己所在部门和上级部门id集合，用{@link #regex} 符号隔开
     *
     * @param userId
     * @return
     */
    protected String getUserDeptIds(String userId) {
        //用户部门
        List<DepartmentUserModel> departmentUserModels = this.getOrganizationFacade().getDepartmentUsersByUserId(userId);
        List<String> collect = departmentUserModels.stream().map(model -> model.getDeptId()).collect(Collectors.toList());
        List<DepartmentModel> departmentModels = this.getOrganizationFacade().getDepartmentsByDeptIds(collect);
        //用户所属部门
        String deptIds = departmentModels.stream().map(model -> model.getId()).collect(Collectors.joining(regex));
        return deptIds;
    }

    /**
     * 从传入参数的所选用户列表中移除所有参与人
     * @param userSelectionVOS 可选用户
     * @param participants 所有参与人，流程中涉及到的参与人
     */
    protected void removeParticipants(List<UserSelectionVO> userSelectionVOS, Set<String> participants) {
        if(CollectionUtils.isNotEmpty(participants)){
            if(CollectionUtils.isEmpty(userSelectionVOS)){
                return;
            }
            Iterator<UserSelectionVO> iterator = userSelectionVOS.iterator();
            while (iterator.hasNext()){
                UserSelectionVO vo = iterator.next();
                if(participants.contains(vo.getId())){
                    iterator.remove();
                }
            }
        }
    }

    private FilterExpression.Item parseFilterExpression(AppFunctionPermissionConditionModel appFunctionPermissionCondition, List<BizPropertyModel> properties) {
        FilterExpression.Op op = disposeDperator(appFunctionPermissionCondition);
        BizPropertyModel bizPropertyModel = properties.stream().filter(t -> t.getCode().equals(appFunctionPermissionCondition.getPropertyCode())).collect(Collectors.toList()).get(0);

        String field = appFunctionPermissionCondition.getPropertyCode();

        if (DefaultPropertyType.CREATER.getCode().equals(appFunctionPermissionCondition.getPropertyCode())
                && (OperatorType.OF.equals(appFunctionPermissionCondition.getOperatorType())
                || OperatorType.NOT_OF.equals(appFunctionPermissionCondition.getOperatorType()))) {
            field = DefaultPropertyType.CREATED_DEPT_ID.getCode();
        }
        if (DefaultPropertyType.OWNER.getCode().equals(appFunctionPermissionCondition.getPropertyCode())
                && (OperatorType.OF.equals(appFunctionPermissionCondition.getOperatorType())
                || OperatorType.NOT_OF.equals(appFunctionPermissionCondition.getOperatorType()))) {
            field = DefaultPropertyType.OWNER_DEPT_ID.getCode();
        }

        if (bizPropertyModel.getPropertyType().equals(BizPropertyType.DATE) && (OperatorType.IS_NOT_NULL == (appFunctionPermissionCondition.getOperatorType()))) {
            field = bizPropertyModel.getCode();
            FilterExpression.Item it = Q.it(field, FilterExpression.Op.NotEq, "");
            return it;
        }

        FilterExpression.Item it = Q.it(field, op, parseValue(appFunctionPermissionCondition, bizPropertyModel));
        return it;
    }

    private Object parseValue(AppFunctionPermissionConditionModel appFunctionPermissionCondition, BizPropertyModel bizPropertyModel) {

        if (StringUtils.isNotEmpty(appFunctionPermissionCondition.getValue()) && (appFunctionPermissionCondition.getOperatorType().equals(OperatorType.OF) ||
                appFunctionPermissionCondition.getOperatorType().equals(OperatorType.NOT_OF))
                && (appFunctionPermissionCondition.getPropertyCode().equals(DefaultPropertyType.CREATER.getCode())
                || appFunctionPermissionCondition.getPropertyCode().equals(DefaultPropertyType.OWNER.getCode()))) {
            List<String> deptIds = Lists.newArrayList();
            try {
                String value = appFunctionPermissionCondition.getValue();
                if (StringUtils.isNotEmpty(value) && !"\"\"".equals(value)) {
                    log.info("部门:" + value);
                    JSONArray depts = JSON.parseArray(value);
                    Iterator<Object> it = depts.iterator();
                    while (it.hasNext()) {
                        deptIds.add(((JSONObject) it.next()).getString(DefaultPropertyType.ID.getCode()));
                    }
                    List<DepartmentModel> departmentModels = getOrganizationFacade().getDepartmentsChildList(deptIds, true);
                    deptIds = departmentModels.stream().map(DepartmentModel::getId).collect(Collectors.toList());
                }
            } catch (JSONException ex) {
                log.error("解析部门异常值:{}", appFunctionPermissionCondition.getValue());
            }
            return deptIds;
        }

        if (StringUtils.isEmpty(appFunctionPermissionCondition.getValue())) {
            if (bizPropertyModel.getPropertyType().equals(BizPropertyType.SHORT_TEXT)
                    && !OperatorType.IS_NOT_NULL.equals(appFunctionPermissionCondition.getOperatorType())
                    && !OperatorType.IS_NULL.equals(appFunctionPermissionCondition.getOperatorType())) {
                return "";
            }
            if (bizPropertyModel.getPropertyType().equals(BizPropertyType.NUMERICAL)
                    && !OperatorType.IS_NOT_NULL.equals(appFunctionPermissionCondition.getOperatorType())
                    && !OperatorType.IS_NULL.equals(appFunctionPermissionCondition.getOperatorType())) {
                return 0;
            }
            return null;
        }
        return appFunctionPermissionCondition.getValue();
    }

    /**
     * 生成部门查询条件
     *
     * @param departQuerCodes 部门编码
     * @return List
     */
    protected List<FilterExpression> getDepartFilter(List<String> departQuerCodes) {
        List<FilterExpression> filterExprs = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(departQuerCodes)) {
            for (String departQuerCode : departQuerCodes) {
                filterExprs.add(Q.it("ownerDeptQueryCode", FilterExpression.Op.LLike, departQuerCode));
            }
        }

        return filterExprs;
    }

    /**
     * 生成部门查询条件
     *
     * @param departments 部门
     * @return List
     */
    protected List<FilterExpression> getDepartFilters(List<DepartmentModel> departments) {
        List<FilterExpression> filterExprs = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(departments)) {
            for (DepartmentModel deptment : departments) {
                filterExprs.add(Q.or(Q.it("ownerDeptQueryCode", FilterExpression.Op.LLike, deptment.getQueryCode()), Q.it("ownerDeptId", FilterExpression.Op.Eq, deptment.getId())));

            }
        }

        return filterExprs;
    }

    /**
     * 解析自定义符号
     *
     * @param appFunctionPermissionCondition
     * @return
     */
    protected FilterExpression.Op disposeDperator(AppFunctionPermissionConditionModel appFunctionPermissionCondition) {
        switch (appFunctionPermissionCondition.getOperatorType()) {
            case EQ:
                return FilterExpression.Op.Eq;
            case GT:
                return FilterExpression.Op.Gt;
            case GTEQ:
                return FilterExpression.Op.Gte;
            case NEQ:
                return FilterExpression.Op.NotEq;
            case CONTAINS:
                return FilterExpression.Op.Like;
            case NOT_CONTAINS:
                return FilterExpression.Op.NotLike;
            case IT:
                return FilterExpression.Op.Lt;
            case ITEQ:
                return FilterExpression.Op.Lte;
            case OF:
                return FilterExpression.Op.In;
            case NOT_OF:
                return FilterExpression.Op.NotIn;
            case IS_NULL:
                return FilterExpression.Op.Eq;
            case IS_NOT_NULL:
                return FilterExpression.Op.NotEq;
            default:
                return null;
        }
    }

    /**
     * 选中数据导出
     *
     * @param objectIds
     * @return
     */
    protected FilterExpression getCheckedFilters(List<String> objectIds) {
        FilterExpression checkedFilter = FilterExpression.empty;
        if (CollectionUtils.isEmpty(objectIds)) {
            return checkedFilter;
        }
        checkedFilter = Q.it(DefaultPropertyType.ID.getCode(), FilterExpression.Op.In, objectIds);
        return checkedFilter;
    }

    /**
     * 根据用户id获取所拥有的部门id （全路径） 因要显示树，所以需要把没有权限的父部门也拿到
     *
     * @param userId
     * @return
     */
    protected Set<String> getManagePermDepartmentId(String userId) {
        //应用管理员管理范围
        Set<String> deptIdSet = new HashSet<>();
        String key = APPNMGCACHEBASE + userId;
        Set<String> cacheSet = (Set<String>) redisTemplate.opsForValue().get(key);
        if (CollectionUtils.isNotEmpty(cacheSet)) {
            return cacheSet;
        }
        AdminModel appAdminByUser = getAppAdminByUserId(userId);
        if (appAdminByUser != null && appAdminByUser.getAdminType() == AdminType.APP_MNG) {
            List<DepartmentScopeModel> departments = appAdminByUser.getDepartments();
            List<String> collect = departments.stream().map(DepartmentScopeModel::getUnitId).collect(Collectors.toList());
            //所有的子部门
            Set<String> deptChildIdSet = getManagePermChildDepartmentId(userId);
            //所有的父部门
            Set<String> parentIdSet = new HashSet<>();
            for (String s : collect) {
                List<String> parentDepartments = getOrganizationFacade().getParentDepartments(s).stream().map(DepartmentModel::getId).collect(Collectors.toList());
                parentIdSet.addAll(parentDepartments);
            }
            deptIdSet.addAll(deptChildIdSet);
            deptIdSet.addAll(parentIdSet);
            //缓存需要在应用管理员更新管理范围时删除
            if (deptIdSet.size() > 0) {
                redisTemplate.opsForValue().set(key, deptIdSet, 360, TimeUnit.SECONDS);
            }
        }
        return deptIdSet;
    }

    /**
     * 获取应用管理员部门管理范围 （部门+子部门）
     *
     * @param userId
     * @return
     */
    protected Set<String> getManagePermChildDepartmentId(String userId) {
        String key = APPNMGCHILDCACHEBASE + userId;
        Set<String> cacheSet = (Set<String>) redisTemplate.opsForValue().get(key);
        if (CollectionUtils.isNotEmpty(cacheSet)) {
            return cacheSet;
        }
        AdminModel appAdminByUser = getAppAdminByUserId(userId);
        if (appAdminByUser != null && appAdminByUser.getAdminType() == AdminType.APP_MNG) {
            List<DepartmentScopeModel> departments = appAdminByUser.getDepartments();
            List<String> collect = departments.stream().map(DepartmentScopeModel::getUnitId).collect(Collectors.toList());
            Set<String> deptChildIdSet = getOrganizationFacade().getDepartmentsChildList(collect, false)
                    .stream().map(DepartmentModel::getId).collect(Collectors.toSet());

            //缓存需要在应用管理员更新管理范围时删除
            if (deptChildIdSet != null && deptChildIdSet.size() > 0) {
                redisTemplate.opsForValue().set(key, deptChildIdSet, 360, TimeUnit.SECONDS);
            }
            return deptChildIdSet;
        }
        return new HashSet<>();
    }

    protected void removeManagePermChildDepartmentId(String userId) {
        redisTemplate.delete(APPNMGCACHEBASE + userId);
        redisTemplate.delete(APPNMGCHILDCACHEBASE + userId);
    }

    protected void setRoleName(String id, UserSelectionVO userSelectionVO) {
        List<String> idList = ImmutableList.of(id);
        Map<String, List<RoleModel>> roleMap = getOrganizationFacade().getRolesByUserIds(idList);
        List<RoleModel> roleList = null;
        if (roleMap != null) {
            roleList = roleMap.get(id);
        }
        if (roleList != null) {
            List<String> roleNameList = roleList
                    .stream().filter(Objects::nonNull).map(RoleModel::getName).collect(Collectors.toList());
            List<String> roleIds = roleList.stream().filter(Objects::nonNull).map(RoleModel::getId).collect(Collectors.toList());
            if (!roleNameList.isEmpty()) {
                userSelectionVO.setRoleName(String.join(",", roleNameList));
                userSelectionVO.setRoleIds(roleIds);
            }
        }
    }

    protected List<DepartmentModel> filterManagerDept(AdminModel appAdminByUser,List<DepartmentModel> departmentList){

        if (appAdminByUser!=null && AdminType.APP_MNG == appAdminByUser.getAdminType()) {
            //需要根据管理员管理范围过滤
            Set<String> deptSet = getManagePermDepartmentId(getUserId());
            if (CollectionUtils.isEmpty(deptSet)) {
                departmentList = Lists.newArrayList();
            }

            if (CollectionUtils.isNotEmpty(departmentList) && deptSet.size() > 0){
                Set<String> finalDeptSet = deptSet;
                departmentList = departmentList.stream().filter(dept -> finalDeptSet.contains(dept.getId())).collect(Collectors.toList());
            }

        }
        return departmentList;
    }

}
